package org.jix.weblog.module.common.exception;

import lombok.extern.slf4j.Slf4j;
import org.jix.weblog.module.common.enums.ResponseCodeEnum;
import org.jix.weblog.module.common.utils.Response;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.security.access.AccessDeniedException;
import javax.servlet.http.HttpServletRequest;

import java.util.Optional;

/**
 * @version 1.0
 * @Author Jix
 * @Date 2024/7/16 16:10
 * @注释
 */

@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 捕获自定义业务异常
     * @return
     */
    @ExceptionHandler(value = BizException.class)
    @ResponseBody
    public Response<Object> handleException(HttpServletRequest request,BizException exception) {
        log.warn("{} request fail, errorCode: {}, errorMessage: {}",
                request.getRequestURI(), exception.getErrorCode(), exception.getMessage());
        return Response.fail(exception);
    }

    /**
     * 捕获其他类型异常
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Response<Object> handleOtherException(HttpServletRequest request, Exception e) {
        log.error("{} request error, ", request.getRequestURI(), e);
        return Response.fail(ResponseCodeEnum.SYSTEM_ERROR);
    }

    /**
     * 捕获参数校验异常
     * @param request
     * @param exception
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseBody
    public Response<Object> handleMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException exception) {
        //参数错误异常码
        String errorCode = ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode();
        String errorMessage = ResponseCodeEnum.PARAM_NOT_VALID.getErrorMessage();
        //获取BindingResult
        BindingResult bindingResult = exception.getBindingResult();
        StringBuilder stringBuilder = new StringBuilder();
        //获取校验不通过的字段
        Optional.ofNullable(bindingResult.getFieldErrors()).ifPresent(errors -> {
            errors.forEach(error ->
                    stringBuilder.append(error.getField())
                            .append(" ")
                            .append(error.getDefaultMessage())
                            .append(", 当前值: '")
                            .append(error.getRejectedValue())
                            .append("'; ")
            );
        });
        //错误信息
        String errorMsg = stringBuilder.toString();
        log.warn("{} request error, errorCode: {}, errorMessage: {}", request.getRequestURI(), errorCode, errorMessage);
        return Response.fail(errorCode, errorMsg);
    }
    @ExceptionHandler({AccessDeniedException.class})
    public void throwAccessDeniedException(AccessDeniedException exception) throws AccessDeniedException {
        // 捕获到鉴权失败异常，主动抛出，交给 RestAccessDeniedHandler 去处理
        log.info("==========捕获到AccessDeniedException=========");
        throw exception;
    }
}
